#include "uart.h"
#include "device.h"
#include <stdint.h>
#include <string.h>

DEV_REG_DEF(uart, Uart_t)

DEV_RET_t
uart_transmit(Device_t* pstDevice, uint8_t* pu8Data, uint32_t u32Len){

    // 输入参数检查
    if(NULL == pstDevice || NULL == pstDevice->pvFeature|| NULL == pu8Data || u32Len < 1) return DEV_PARAM_ERR;

    // 设备检测
    CHECK_DEVICE(pstDevice);

    // 转换为Uart_t结构体
    Uart_t *pstUart = (Uart_t*)(pstDevice->pvFeature);

    // 输入参数检查
    if(NULL == pstUart->HW.pfnReceive || NULL == pstUart->HW.pfnTransmit) {DEV_RETURN(DEV_PARAM_ERR)};

    // 调用内部实现
    uint8_t u8Ret = pstUart->HW.pfnTransmit(pu8Data, u32Len);

    // 返回执行结果
    DEV_RETURN(u8Ret);
}

DEV_RET_t
uart_monitor(Device_t* pstDevice){

    // 输入参数检查
    if(NULL == pstDevice || NULL == pstDevice->pvFeature) return DEV_PARAM_ERR;

    // 设备检测
    CHECK_DEVICE(pstDevice);

    // 转换为Uart_t结构体
    Uart_t *pstUart = (Uart_t*)(pstDevice->pvFeature);

    // 输入参数检查
    if(NULL == pstUart->HW.pfnReceive || NULL == pstUart->SW.pu8Data || 
        0 == pstUart->SW.u32Len) {DEV_RETURN(DEV_PARAM_ERR)};

    // 接收数据
    uint32_t u32Length = 0;
    uint32_t u32OldLength = 0;
    uint32_t u32TimeOut = 0;

    // 多次循环判断数据是否接收完成
    while(1)
    {
        // 接收数据
        u32OldLength = pstUart->HW.pfnReceive(pstUart->SW.pu8Data, pstUart->SW.u32Len);
        
        // 超时计数器加
        u32TimeOut++;

        // 长度判断
        if(u32OldLength > 0 && u32Length != u32OldLength) {

            // 更新长度
            u32Length = u32OldLength;

            // 重新等待
            u32TimeOut = 0;
        }

        // 超时判断
        if(u32TimeOut > pstUart->SW.u32TimeOut) break;

        // 延时判断
        DEV_DELAY_MS(1);
    }
    
    // 长度是否符合要求
    if(u32Length < 1 || u32Length > pstUart->SW.u32Len) {DEV_RETURN(DEV_OK)};

    // 计算缓存位置
    pstUart->SW.u32Tail = pstUart->SW.u32Len - u32Length;

    // 判断是否接收完成
    if(pstUart->SW.u32Tail != pstUart->SW.u32Head){
        set_device_event(pstDevice, UART_DATA_READY);
        pstUart->SW.u32Index = u32Length;
    }
    
    // UART执行成功
    DEV_RETURN(DEV_OK);
}

uint32_t
uart_receive(Device_t* pstDevice, uint8_t* pu8Data){

    // 输入参数检查
    if(NULL == pstDevice || NULL == pstDevice->pvFeature) return 0;

    // 设备检测
    CHECK_DEVICE(pstDevice);
    
    // 转换为Uart_t结构体
    Uart_t *pstUart = (Uart_t*)(pstDevice->pvFeature);

    // 输入参数检查
    if(NULL == pstUart->HW.pfnReceive || NULL == pstUart->SW.pu8Data || 
        0 == pstUart->SW.u32Len) {DEV_RETURN(0)};

    // 接收长度
    uint32_t u32Count = 0;

    // 计算接收长度并拷贝到目标地址
    if(pstUart->SW.u32Tail > pstUart->SW.u32Head){

        // 计算长度
        u32Count = pstUart->SW.u32Tail - pstUart->SW.u32Head;

        // 拷贝数据
        memcpy(pu8Data,pstUart->SW.pu8Data+pstUart->SW.u32Head,u32Count);
    }
    else{

        // 计算长度
        u32Count = ( pstUart->SW.u32Len - pstUart->SW.u32Head) + pstUart->SW.u32Tail;

        // 跨区段拷贝数据
        memcpy(pu8Data,pstUart->SW.pu8Data+pstUart->SW.u32Head, 
            pstUart->SW.u32Len - pstUart->SW.u32Head);

        memcpy(pu8Data +  pstUart->SW.u32Len - pstUart->SW.u32Head,
            pstUart->SW.pu8Data,pstUart->SW.u32Tail);
    }

    // 计算新的头位置
    pstUart->SW.u32Head = pstUart->SW.u32Tail;

    // 返回接收长度
    DEV_RETURN(u32Count);
}
